package cn.com.yto56.cainiao.exponent.elasticsearch.service;

import cn.com.yto56.basic.framework.core.sercurity.MD5;
import cn.com.yto56.basic.framework.core.util.DateUtil;
import cn.com.yto56.basic.framework.plugin.elasticsearch.ElasticSearchStarter;
import cn.com.yto56.cainiao.exponent.dto.ExponentRequest;
import cn.com.yto56.cainiao.exponent.dto.QueryESRequest;

import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cn.com.yto56.cainiao.exponent.dto.QueryESResponse;
import com.alibaba.fastjson.JSON;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.text.StrSubstitutor;
import org.frameworkset.elasticsearch.client.ClientInterface;
import org.frameworkset.elasticsearch.entity.MapRestResponse;
import org.frameworkset.elasticsearch.entity.MapSearchHit;

public final class CommonService {

    private static final String INDEX_TYPE = "exponent-origin";
    private static final String PATH_FORMAT = "/" + INDEX_TYPE + "-%s/" + INDEX_TYPE + "/_search";
    public static String INDEX_DATE_PATTEN = "yyyy.MM";

    public static String getTrackESPath(final Date pullDate) {
        return String.format(PATH_FORMAT, DateUtil.getFormatedDate(pullDate, INDEX_DATE_PATTEN));
    }

    public static String generateESId(ExponentRequest request) {
        return MD5.encryptMD5(String.format("%s-%s-%s", request.getWayBillNo(), request.getExponentType(), request.getExponetMsg()));
    }

    public static String getAgg(final QueryESRequest qe) {
        if (qe == null) {
            return "";
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        StringBuilder builder = new StringBuilder();
        builder.append("{\"size\":0,\"query\":{\"bool\":{\"must\":[{\"range\":{\"pullDate\":{");
        Calendar c = Calendar.getInstance();
        c.setTime(qe.getPullDate());
        c.add(Calendar.DAY_OF_MONTH, 1);
        builder.append("\"gte\":").append("\"").append(simpleDateFormat.format(qe.getPullDate())).append("T00:00:00.000+08:00\"");
        builder.append(",");
        builder.append("\"lte\":").append("\"").append(simpleDateFormat.format(c.getTime())).append("T00:00:00.000+08:00\"");
        builder.append("}}},{\"match\":{\"exponentType\":");
        builder.append("\"").append(qe.getExponentType()).append("\"");
        builder.append("}}]}}");
        if (qe.getFiled() != null && qe.getFiled().length() > 0) {
            builder.append(",\"aggs\":{\"group\":{\"terms\":{\"field\":");
            builder.append("\"").append(qe.getFiled()).append("\"");
            builder.append("}}}");
        }
        builder.append("}");
        return builder.toString();
    }

    public static String compileString(String source, Map<String, String> parameter) {
        StrSubstitutor strSubstitutor = new StrSubstitutor(parameter, "${", "}");
        strSubstitutor.setEnableSubstitutionInVariables(true);
        return strSubstitutor.replace(source);
    }

    public static Map<String, String> getSearchTime(Date date, int step) {
        int s = step == 0 ? 1 : step;
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Map<String, String> map = new HashMap<>();
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(Calendar.DAY_OF_MONTH, s);
        if (s > 0) {
            map.put("startTime", simpleDateFormat.format(date));
            map.put("endTime", simpleDateFormat.format(c.getTime()));
        } else {
            map.put("endTime", simpleDateFormat.format(date));
            map.put("startTime", simpleDateFormat.format(c.getTime()));
        }
        return map;
    }

    public static String convertInputStream(final InputStream inputStream) throws IOException {
        return IOUtils.toString(inputStream, "utf-8");
    }

    public static MapRestResponse search(ClientInterface client, String path, String entity) {
        return client.search(path, entity);
    }

    public static QueryESResponse searchById(ClientInterface client, String id) {
        List<MapSearchHit> mapSearchHits = client.search("_search", "{\"query\":{\"ids\":{\"values\":[\"" + id + "\"]}}}").getSearchHits().getHits();
        if (mapSearchHits.size() > 0) {
            MapSearchHit mapSearchHit = mapSearchHits.get(0);
            QueryESResponse response = new QueryESResponse();
            response.setIndex(mapSearchHit.getIndex());
            response.setType(mapSearchHit.getType());
            response.setId(mapSearchHit.getId());
            response.setData(JSON.toJSONString(mapSearchHit.getSource()));
            return response;
        }
        return null;
    }

    public static String update(ClientInterface client, String path, String entity) {
        return client.updateByPath(path + "/_update", entity);
    }

    public static String update(ClientInterface client, QueryESResponse response, ExponentRequest request) {
        return client.addDocumentWithId(
                response.getIndex(),
                INDEX_TYPE,
                request,
                MD5.encryptMD5(String.format("%s-%s-%s", request.getWayBillNo(), request.getExponentType(), request.getExponetMsg()))
        );
    }

    public static long getDateDiffHour(Date dt1, Date dt2) {
        return (dt1.getTime() - dt2.getTime()) / 3600000;
    }
}
